#!/bin/bash


trap "kill  $! 2>/dev/null; echo ' [-] Exiting....'" INT


VERSION="0.0.2"

log="$PWD/log.$(date +%T-%F).txt"

cecho() {
	echo -e "$1"
	echo -e "$1" >>"$log"
	tput sgr0;
}

ncecho () {
	echo -ne "$1"
	echo -ne "$1" >>"$log"
	tput sgr0
}

usage () {
	cecho " Mandatory options:"
	cecho "   -i - Input File"
	cecho ""
	cecho " Optional options:"
	cecho "   -o - Output File"
	cecho "   -fps - Output fps"
	cecho "   --keep-temp - Keeps temporary files"
	cecho ""

}

autocrop () {
	CROP="1"
	TOTAL_LOOPS="10"
	NICE_PRI="10"
	VF_OPTS="pp=lb,"



	######### CROP Settings #############
	if [ "$CROP" -eq "1" ]; then
		A=0
		while [ "$A" -lt "$TOTAL_LOOPS" ] ; do
			A="$(( $A + 1 ))"
			SKIP_SECS="$(( 35 * $A ))"
  
			nice -n $NICE_PRI nohup mplayer "$SOURCE" -ss $SKIP_SECS -identify -frames 20 -vo md5sums -ao null -nocache -vf ${VF_OPTS}cropdetect=20:16 >> "$log" 2>&1
  
			CROP[$A]=`awk -F 'crop=' '/crop/ {print $2}' < "$log" | awk -F ')' '{print $1}' | tail -n 1`
		done
		rm md5sums 

  		B=0
		while [ "$B" -lt "$TOTAL_LOOPS" ] ; do
			B="$(( $B + 1 ))"
  
			C=0
			while [ "$C" -lt "$TOTAL_LOOPS" ] ; do
				C="$(( $C + 1 ))"
  
				if [ "${CROP[$B]}" == "${CROP[$C]}" ] ; then
					COUNT_CROP[$B]="$(( ${COUNT_CROP[$B]} + 1 ))"
				fi
			done  
		done
  
		HIGHEST_COUNT=0
  
		D=0
		while [ "$D" -lt "$TOTAL_LOOPS" ] ; do
			D="$(( $D + 1 ))"
  
			if [ "${COUNT_CROP[$D]}" -gt "$HIGHEST_COUNT" ] ; then
				HIGHEST_COUNT="${COUNT_CROP[$D]}"
				GREATEST="$D"
			fi
		done
  
		CROPCODE="cropcode=${CROP[$GREATEST]}"
  
		echo -e "$CROPCODE" >> "$log" 2>&1

	fi
}

sp="/-\|"
spinny () {
	echo -ne "\b${sp:i++%${#sp}:1}"
}

progress () {
	ncecho "  ";
	while [ /bin/true ]; do
		kill -0 $pid 2>/dev/null;
		if [[ $? = "0" ]]; then
			spinny
			sleep 0.25
		else
			ncecho "\b\b";
			wait $pid
			retcode=$?
			echo "$pid's retcode: $retcode" >> "$log"
			if [[ $retcode = "0" ]]; then
				cecho success
			else
				cecho failed
				echo -e " [-] Showing the last 5 lines from the logfile ($log)...";
				tail -n5 "$log"
				exit 1;
			fi
			break 2;
		fi
	done
} 

if [[ $# -lt 1 ]];
then
	cecho ' [-] Please supply a filename to remux to MP4, and the target filename optionally';
	exit 1;
fi

for i in mplayer ffmpeg mkvinfo mkvextract neroAacEnc mp4creator MP4Box aften; do
	if hash -r "$i" >/dev/null 2>&1; then
		ncecho;
	else
		cecho " [-] The $i command is not available, please install the required packages.";
		DIE=1;
	fi
done


if [[ $DIE ]]; then
	cecho " [-] Needed programs weren't found, exiting...";
	rm -f "$log" > /dev/null 2>&1
	exit 1;
fi
#Get command line arguments		
while [ $# -gt 0 ] 
	do
	 case $1 in 
		-i) SOURCE=$2; shift 2 ;;
		-o) DEST=$2; shift 2 ;;
		-fps) OUTPUT_FPS=$2; shift 2 ;;
		-keep-temp) KEEP_TEMP=1; shift 1 ;;
		--keep-temp) KEEP_TEMP=1; shift 1 ;;
		--audio-track) AUDIO_TRACK=$2; shift 2 ;;
		*) usage; exit 1 ;;
	esac
done 

if [[ -z $SOURCE ]]; then
	usage;
	rm -f "$log" > /dev/null 2>&1
	exit 1;
fi

if [[ -z $DEST ]];
then
	DEST="${SOURCE%.*}.mp4"
fi

cecho " [+] Source filename: $SOURCE\n [+] Destination filename: $DEST";

if [[ -f $DEST ]];
then
	cecho ' [-] Destination filename already exists -- please delete and rerun the script, or select another destination';
	rm -f "$log" > /dev/null 2>&1
	exit 1;
fi



identify() {
	mplayer -frames 0 -identify -ao null -vo null "$SOURCE" 2>/dev/null | tee -a "$log" > /tmp/info.$$.txt
	grep ^ID_VIDEO /tmp/info.$$.txt >/dev/null && VIDEO=1
	grep ^ID_AUDIO /tmp/info.$$.txt >/dev/null && AUDIO=1

	WIDTH=$(grep ^ID_VIDEO_HEIGHT /tmp/info.$$.txt | sed 's/^ID_VIDEO_HEIGHT=//g')
	if [[ -z $WIDTH ]]; then
		cecho " [-] The width could not be identified."
		exit 1;
	fi
	HEIGHT=$(grep ^ID_VIDEO_WIDTH /tmp/info.$$.txt | sed 's/^ID_VIDEO_WIDTH=//g')
	if [[ -z $HEIGHT ]]; then
		cecho " [-] The height could not be identified."
		exit 1;
	fi
	FPS=$(grep ^ID_VIDEO_FPS /tmp/info.$$.txt | sed 's/^ID_VIDEO_FPS=//g')
	if [[ -z $FPS ]]; then
		cecho " [-] The fps could not be identified."
		exit 1;
	fi
	VIDEO_CODEC=$(grep ^ID_VIDEO_CODEC /tmp/info.$$.txt | awk -F= '{print $2}')
	if [[ -z $VIDEO_CODEC ]]; then
		cecho " [-] The video codec could not be identified."
		exit 1;
	fi
	AUDIO_CHANNELS=$(grep ^ID_AUDIO_NCH /tmp/info.$$.txt | sort -r | head -n1 | awk -F= '{print $2}')
	if [[ -z $AUDIO_CHANNELS ]]; then
		cecho " [-] The audio channels could not be identified."
		exit 1;
	fi
	AUDIO_CODEC=$(grep ^ID_AUDIO_CODEC /tmp/info.$$.txt | awk -F= '{print $2}')
	if [[ -z $AUDIO_CODEC ]]; then
		cecho " [-] The audio codec could not be identified."
		exit 1;
	fi

	if [ "$AUDIO_CODEC" = "fftruehd" ]; then
		AUDIO_EXT=".thd"
	elif [ "$AUDIO_CODEC" = "ffaac" ]; then
		AUDIO_EXT=".aac"
	elif [ "$AUDIO_CODEC" = "ffdts" ]; then
		AUDIO_EXT=".dts"
	elif [ "$AUDIO_CODEC" = "ffeac3" ]; then
		AUDIO_EXT=".ec3"
	elif [ "$AUDIO_CODEC" = "ffac3" ]; then
		AUDIO_EXT=".ac3"
	elif [ "$AUDIO_CODEC" = "ffflac" ]; then
		AUDIO_EXT=".flac"
	else
		cecho " [-] Unknown audio codec...please submit $log to the developer" 
	fi

	AUDIO_FORMAT=$(grep ^ID_AUDIO_FORMAT /tmp/info.$$.txt | awk -F= '{print $2}')
	AUDIO_RATE=$(grep ^ID_AUDIO_RATE /tmp/info.$$.txt | awk -F= '{print $2}' | head -n1 | awk '{print $1}')
	DEMUXER=$(grep ^ID_DEMUXER /tmp/info.$$.txt | awk -F= '{print $2}')
	CHAPTERS=$(grep ^ID_CHAPTERS /tmp/info.$$.txt | awk -F= '{print $2}')
	rm -f /tmp/info.$$.txt

	size=$(du -m "$SOURCE" | awk '{print $1}');
	if [[ -z $VIDEO ]];
	then
		cecho " [-] Missing a video stream -- please check the source file.";
		exit 1;
	else
		cecho " [+] Video stream found, $HEIGHT x $WIDTH @ $FPS fps, using $VIDEO_CODEC";
	fi

	if [[ -z $AUDIO ]];
	then
		cecho " [-] Missing a audio stream -- please check the source file.";
		exit 1;
	else
		cecho " [+] Audio stream found, $AUDIO_CHANNELS audio channels, using $AUDIO_CODEC"; 
	fi
	cecho " [+] Muxed in $DEMUXER format, source file is ${size}MB";
}

dumpAndReencodeAudio() {
	#AUDIO_TRACK=`mkvinfo "$SOURCE" | grep -B2 -A8 "Track type: audio" | head -n1 | awk -F": " '{print $2}'`
	#if [[ -z $AUDIO_TRACK ]]; then
	#	cecho " [-] The audio track could not be identified"
	#	exit 1;
	#fi


	#ncecho " [+] Extracting the audio from MKV container...";
	#mkvextract tracks "$SOURCE" "$AUDIO_TRACK":"$SOURCE$AUDIO_EXT" >> "$log" 2>&1 &
	#pid=$!;progress $pid
	
	#ncecho " [+] Decoding to stereo uncompressed audio...";
	ncecho " [+] Encoding the audio to low-complexity AAC...";
	
	if [[ ! -z $AUDIO_TRACK ]]; then

		ffmpeg -i "$SOURCE" -vn -map 0.$AUDIO_TRACK -ac 2 -acodec pcm_s16le -async 1 -f wav pipe:1 2>/dev/null | neroAacEnc -ignorelength -lc -q 0.6 -if - -of "$DEST.m4a" >> "$log" 2>&1 &
	else
		ffmpeg -i "$SOURCE" -vn -map 0.1 -ac 2 -acodec pcm_s16le -async 1 -f wav pipe:1 2>/dev/null | neroAacEnc -ignorelength -lc -q 0.6 -if - -of "$DEST.m4a" >> "$log" 2>&1 &
	fi
	pid=$!;progress $pid

	#if [[ ! -f "$DEST.wav" || ! -s "$DEST.wav" ]];then 
	#	cecho " [-] ffmpeg does not recognize the audio codec...";
	#	exit 1;
	#fi

	#neroAacEnc -lc -q 0.6 -if "$DEST.wav" -of "$DEST.m4a" >> "$log" 2>&1 &
	#pid=$!;progress $pid

	
	#rm -f "$DEST.wav"

		
	ncecho " [+] Extracting audio from MP4 container (silly neroAacEnc)...";
        MP4Box -raw 1 "$DEST.m4a" >>"$log" 2>&1 &
	pid=$!;progress $pid
	mv "${DEST}_track1.aac" "$DEST.aac"
	rm -f "$DEST.m4a"
	AUDIO_FILE="$DEST.aac"
	sleep 1;	



	#Check to see if Dolby Digital is an option
	if (( "$AUDIO_CHANNELS" > 2 )); then
	

	#	ncecho " [+] Decoding to $AUDIO_CHANNELS channel uncompressed audio..."
		ncecho " [+] Encoding the audio to $AUDIO_CHANNELS channel Dolby Digital..."
	if [[ ! -z $AUDIO_TRACK ]]; then
		ffmpeg -i "$SOURCE" -map 0.$AUDIO_TRACK -vn -ac "$AUDIO_CHANNELS" -acodec pcm_s16le -async 1 -f wav pipe:1 2>/dev/null | aften -b 448 - "$DEST.ac3" >> "$log"  2>&1 &
	else
		ffmpeg -i "$SOURCE" -map 0.1 -vn -ac "$AUDIO_CHANNELS" -acodec pcm_s16le -async 1 -f wav pipe:1 2>/dev/null | aften -b 448 - "$DEST.ac3" >> "$log"  2>&1 &
	fi
		


		pid=$!;progress $pid
		#rm -f "$DEST.wav" >> "$log" 2>&1 &
		AC3_FILE="$DEST.ac3"
	fi

	#ncecho " [+] Removing temporary audio file...";
	#rm -f "$SOURCE$AUDIO_EXT" >> "$log" 2>&1 &
	#pid=$!;progress $pid
}

reencodeVideo() {
	if [[ ! -z $CHAPTERS  && "$CHAPTERS" -gt "0" ]]; then
		ncecho " [+] Extacting chapter information...";
		mkvextract chapters -s "$SOURCE" > "$DEST.txt" 2>/dev/null &
		pid=$!;progress $pid
	fi

	ncecho " [+] Extracting auto-crop settings from the video...";
	autocrop &
	pid=$!;progress $pid
	CROP=`tail -n5 "$log" | grep cropcode | awk -F 'cropcode=' '/cropcode/ {print $2}'`

	ncecho " [+] Encoding the video from the mkv...";
	ffmpeg -i "$SOURCE" -an -vsync 0 -vf "crop=$CROP" -vcodec libx264 -flags +loop -cmp +chroma -partitions +parti8x8+parti4x4+partp8x8+partb8x8 -me_method umh -coder 1 -subq 8 -me_range 16 -g 250 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -b_strategy 2 -qcomp 0.6 -qmin 10 -qmax 51 -qdiff 4 -bf 3 -refs 5 -directpred 3 -trellis 1 -flags2 +bpyramid+mixed_refs+wpred+dct8x8+fastpskip -wpredp 2 -rc_lookahead 50 -crf 22 -level 31 -threads 0 -f h264 "$DEST.264" >> "$log" 2>&1 &


	pid=$!;progress $pid
	VIDEO_FILE="$DEST.264"

}

mux() {
	if [ -z "$VIDEO_FILE" ]; then	
		VIDEO_FILE="$DEST.264"
	fi


#	ncecho " [x] Muxing video stream at $OUTPUT_FPS fps...";
#	mp4creator --create="$VIDEO_FILE" "$DEST" -r "$OUTPUT_FPS" >>"$log" 2>&1 &
#	pid=$!;progress $pid

#	ncecho " [x] Muxing the AAC audio stream...";
#	mp4creator --create="$AUDIO_FILE" "$DEST" >>"$log" 2>&1 &
#	pid=$!;progress $pid

	ncecho " [+] Muxing audio and video streams...";

	if (( "$AUDIO_CHANNELS" > 2 )); then
		if [[ ! -f "$DEST.txt" || ! -s "$DEST.txt" ]]; then
			MP4Box -add "$VIDEO_FILE" -add "$AUDIO_FILE" -add "$AC3_FILE" -fps "$OUTPUT_FPS" "$DEST" >> "$log" 2>&1 &
		else
			MP4Box -add "$VIDEO_FILE" -add "$AUDIO_FILE" -add "$AC3_FILE" -chap "$DEST.txt" -fps "$OUTPUT_FPS" "$DEST" >> "$log" 2>&1 &
		fi
	else
		MP4Box -add "$VIDEO_FILE" -add "$AUDIO_FILE" -fps "$OUTPUT_FPS" "$DEST" >> "$log" 2>&1 &
	fi

	pid=$!;progress $pid


	if [[ -z $KEEP_TEMP ]]; then
		ncecho " [+] Deleting audio and video tempfiles...";
		rm -f "$VIDEO_FILE" "$AUDIO_FILE" "$AC3_FILE" "$DEST.txt" >>"$log" 2>&1 &
		pid=$!;progress $pid
	fi
	
}

finish() {
	cecho " [o] All done!";
}

if [[ -z $OUTPUT_FPS ]]; then
	OUTPUT_FPS="$FPS"
fi

identify;
reencodeVideo;
dumpAndReencodeAudio;
mux;
finish;

rm -f "$log"
